#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


#define NUM 1024

struct My_File
{
  int fd;
  char buffer[NUM];
  int end;  // 记录缓冲区末尾
};

typedef struct My_File My_File;

My_File* fopen_(const char* path, const char* mode)
{
  assert(path);
  assert(mode);
  My_File* file = NULL;

  if (strcmp(mode, "w") == 0)
  {
     file = (My_File*)malloc(sizeof (My_File));
     file->fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, 0666);
      if (file->fd < 0)
      {
          perror("fail open");
          // 在底层为fopen进行调用
          // 没找到，则要free掉malloc结构体
          free(file);
          return NULL;    
      }
      // 成功打开文件，就要对缓冲区进行处理
      memset(file->buffer, '0', sizeof(file->buffer));
      file->end = 0;
      return file;
  }
  else if (strcmp(mode, "w+") == 0)
  {

  }
  else if (strcmp(mode, "r") == 0)
  {

  }
  else if (strcmp(mode, "r+") == 0)
  {

  }
  else if (strcmp(mode, "a") == 0)
  {

  }
  else if (strcmp(mode, "a+") == 0)
  {

  }else 
  {
    // 都没有匹配
  }
  
  return file;
}

int fflush_(My_File* file)
{
  assert(file);
  if (file->end != 0)
  {
  write(file->fd, file->buffer, file->end);
  // 然后调用一个系统级的刷新函数
  syncfs(file->fd);
   file->end = 0;
  } 
  return 0;
}


int fputs_(const char* str, My_File* file)
{
   // 底层还是调用write
   assert(str);
   assert(file);
   // strcpy 一定得跟这end走，不然会出现数据覆盖的问题
   strcpy(file->buffer + file->end, str);
   file->end = file->end + strlen(str);

   // 测试一下标准输出
   // file->fd = 1;

   if (file->fd == 1)
   {
     // 标准输出,关于标准输出的策略，我们可以只需给缓冲区，
     // 其余交给标准输出文件自己的刷新策略。
     if (file->buffer[file->end - 1] == '\n')
     {
       write(1, file->buffer, file->end);
       file->end = 0;
     }
   }else if (file->fd == 2)
   {
     //标准错误输出
     
   }


   return 0;
}


void fclose_(My_File* file)
{
  assert(file);
  fflush_(file);
   free(file);
}




